home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / dwmain.cpp < prev    next >
C/C++ Source or Header  |  1997-05-29  |  10KB  |  413 lines

  1. /* Copyright (C) 1996, 1997, Russell Lang.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19.  
  20. // dwmain.cpp
  21. // Ghostscript DLL loader for Windows
  22.  
  23. #define STRICT
  24. #include <windows.h>
  25. #include <shellapi.h>
  26. #ifndef __WIN32__
  27. #include <toolhelp.h>
  28. static BOOL dllfix(void);
  29. #endif
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <dos.h>
  34. extern "C" {
  35. #include "gscdefs.h"
  36. #define GSREVISION gs_revision
  37. #include "gsdll.h"
  38. }
  39. #include "dwmain.h"
  40. #include "dwdll.h"
  41. #include "dwtext.h"
  42. #include "dwimg.h"
  43.  
  44. #if defined(_MSC_VER) && defined(__WIN32__)
  45. #define _export
  46. #endif
  47.  
  48. /* public handles */
  49. HINSTANCE ghInstance;
  50.  
  51. /* redirected stdio */
  52. TextWindow tw;
  53.  
  54. const LPSTR szAppName = "Ghostscript";
  55.  
  56. #ifdef __WIN32__
  57. const LPSTR szIniName = "GSWIN32.INI";
  58. const char *szDllName = "GSDLL32.DLL";
  59. #else
  60. const LPSTR szIniName = "GSWIN.INI";
  61. const char *szDllName = "GSDLL16.DLL";
  62. #endif
  63. const LPSTR szIniSection = "Text";
  64.  
  65. int dll_exit_status;
  66.  
  67. int FAR _export gsdll_callback(int message, char FAR *str, unsigned long count);
  68.  
  69. // the Ghostscript DLL class
  70. gsdll_class gsdll;
  71.  
  72. char start_string[] = "systemdict /start get exec\n";
  73.  
  74. // program really starts at WinMain
  75. int
  76. new_main(int argc, char *argv[])
  77. {
  78. typedef char FAR * FARARGV_PTR;
  79. FARARGV_PTR *far_argv;
  80. int rc;
  81.  
  82.     // load DLL
  83.     if (gsdll.load(ghInstance, szDllName, GSREVISION)) {
  84.     char buf[256];
  85.     gsdll.get_last_error(buf, sizeof(buf));
  86.     tw.puts(buf);
  87.     return 1;
  88.     }
  89.  
  90.     
  91. #ifdef __WIN32__
  92.     far_argv = argv;
  93. #else
  94.     far_argv = new FARARGV_PTR[argc+1];
  95.     if (!far_argv)
  96.     return 1;
  97.     for (int i = 0; i<argc; i++)
  98.     far_argv[i] = argv[i];    // convert from near to far pointers
  99.     far_argv[i+1] = NULL;
  100. #endif
  101.  
  102.     // initialize the interpreter
  103.     rc = gsdll.init(gsdll_callback, tw.get_handle(), argc, far_argv);
  104.     if (rc == GSDLL_INIT_QUIT) {
  105.         gsdll.unload();
  106.     return 0;
  107.     }
  108.     if (rc) {
  109.     char buf[256];
  110.     gsdll.get_last_error(buf, sizeof(buf));
  111.     tw.puts(buf);
  112.         gsdll.unload();
  113. #ifndef __WIN32__
  114.     if (rc == GSDLL_INIT_IN_USE)
  115.         dllfix();   // offer option to unload NASTY!
  116. #endif
  117.     return rc;
  118.     }
  119.  
  120.     // if (!batch)
  121.     gsdll.execute(start_string, strlen(start_string));
  122.  
  123. #ifdef UNUSED
  124.     int len;
  125.     char line[256];
  126.     do {
  127.     len = tw.read_line(line, sizeof(line));
  128.     } while ( len && !gsdll.execute(line, len) );
  129. #endif
  130.     
  131.     gsdll.unload();
  132.  
  133.     return 0;
  134. }
  135.  
  136.  
  137. /* our exit handler */
  138. /* also called from Text Window WM_CLOSE */
  139. void win_exit(void)
  140. {
  141.     if (dll_exit_status) {
  142.     /* display message box so error messages in text window can be read */
  143.     char buf[80];
  144.     if (IsIconic(tw.get_handle()))
  145.         ShowWindow(tw.get_handle(), SW_SHOWNORMAL);
  146.     BringWindowToTop(tw.get_handle());  /* make text window visible */
  147.     sprintf(buf, "Exit code %d\nSee text window for details",dll_exit_status);
  148.     MessageBox((HWND)NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
  149.     }
  150. }
  151.  
  152. void
  153. set_font(void)
  154. {
  155.     int fontsize;
  156.     char fontname[256];
  157.     char buf[32];
  158.  
  159.     // read ini file
  160.     GetPrivateProfileString(szIniSection, "FontName", "Courier New", fontname, sizeof(fontname), szIniName);
  161.     fontsize = GetPrivateProfileInt(szIniSection, "FontSize", 10, szIniName);
  162.  
  163.     // set font
  164.     tw.font(fontname, fontsize); 
  165.  
  166.     // write ini file
  167.     WritePrivateProfileString(szIniSection, "FontName", fontname, szIniName);
  168.     sprintf(buf, "%d", fontsize);
  169.     WritePrivateProfileString(szIniSection, "FontSize", buf, szIniName);
  170. }
  171.  
  172. int PASCAL 
  173. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
  174. {
  175. #if defined(_MSC_VER)    /* MSC doesn't give us _argc and _argv[] so ...   */
  176. #define MAXCMDTOKENS 128
  177.     int    _argc=0;
  178.     LPSTR    _argv[MAXCMDTOKENS];
  179.     LPSTR    p, q;
  180. #ifdef __WIN32__
  181.     _argv[_argc] = "gswin32.exe";
  182. #else
  183.     _argv[_argc] = "gswin.exe";
  184. #endif
  185.     // Parse command line handling quotes.
  186.     p = lpszCmdLine;
  187.     while (*p) {
  188.         // for each argument
  189.         while ((*p) && (*p == ' '))
  190.         p++;    // skip over leading spaces
  191.         if (*p == '\042') {
  192.            p++;        // skip "
  193.            q = p;
  194.            // scan to end of argument
  195.            // doesn't handle embedded quotes
  196.            while ((*p) && (*p != '\042'))
  197.             p++;
  198.            _argv[++_argc] = q;
  199.            if (*p)
  200.             *p++ = '\0';
  201.         }
  202.         else if (*p) {
  203.            // delimited by spaces
  204.            q = p;
  205.            while ((*p) && (*p != ' '))
  206.             p++;
  207.            _argv[++_argc] = q;
  208.            if (*p)
  209.             *p++ = '\0';
  210.         }
  211.     }
  212.     _argv[++_argc] = (LPSTR)NULL;
  213. #endif
  214.  
  215.     if (hPrevInstance) {
  216.         MessageBox((HWND)NULL,"Can't run twice", szAppName, MB_ICONHAND | MB_OK);
  217.         return FALSE;
  218.     }
  219.  
  220.     /* copy the hInstance into a variable so it can be used */
  221.     ghInstance = hInstance;
  222.  
  223.  
  224.     /* start up the text window */
  225.     if (!hPrevInstance) {
  226.         HICON hicon = LoadIcon(hInstance, (LPSTR)MAKEINTRESOURCE(GSTEXT_ICON));
  227.         tw.register_class(hInstance, hicon);
  228.     }
  229.     set_font();
  230.     tw.size(80, 80);
  231.     tw.drag("(", ") run\r");
  232.  
  233.     // create the text window
  234.     if (tw.create(szAppName, cmdShow))
  235.         exit(1);
  236.  
  237.     // initialize for image windows
  238.     ImageWindow::hwndtext = tw.get_handle();
  239.     ImageWindow::hInstance = hInstance;
  240.  
  241.     dll_exit_status = new_main(_argc, _argv);
  242.  
  243.      win_exit();
  244.  
  245.     tw.destroy();
  246.  
  247.     return dll_exit_status;
  248. }
  249.  
  250.  
  251. int FAR _export
  252. gsdll_callback(int message, char FAR *str, unsigned long count)
  253. {
  254. char buf[256];
  255. ImageWindow *iw;
  256.     switch (message) {
  257.     case GSDLL_POLL:
  258.         {
  259.         MSG msg;
  260.         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  261.             {
  262.             TranslateMessage(&msg);
  263.             DispatchMessage(&msg);
  264.             }
  265.         }
  266.         // If text window closed then abort Ghostscript
  267.         if (!IsWindow(tw.get_handle()))
  268.         return -1;
  269.         break;
  270.     case GSDLL_STDIN:
  271.         return tw.read_line(str, count);
  272.     case GSDLL_STDOUT:
  273.         if (str != (char *)NULL)
  274.         tw.write_buf(str, count);
  275.         return count;
  276.     case GSDLL_DEVICE:
  277. #ifdef DEBUG
  278.         sprintf(buf,"Callback: DEVICE %p %s\n", (char *)str,
  279.         count ? "open" : "close");
  280.         tw.puts(buf);
  281. #endif
  282.         if (count) {
  283.         iw = new ImageWindow;
  284.         iw->open(str);
  285.         }
  286.         else {
  287.         iw = FindImageWindow(str);
  288.         iw->close();
  289.         }
  290.         break;
  291.     case GSDLL_SYNC:
  292. #ifdef DEBUG
  293.         sprintf(buf,"Callback: SYNC %p\n", (char *)str);
  294.         tw.puts(buf);
  295. #endif
  296.         iw = FindImageWindow(str);
  297.         iw->sync();
  298.         break;
  299.     case GSDLL_PAGE:
  300. #ifdef DEBUG
  301.         sprintf(buf,"Callback: PAGE %p\n", (char *)str);
  302.         tw.puts(buf);
  303. #endif
  304.         iw = FindImageWindow(str);
  305.         iw->page();
  306.         break;
  307.     case GSDLL_SIZE:
  308. #ifdef DEBUG
  309.         sprintf(buf,"Callback: SIZE %p width=%d height=%d\n", (char *)str,
  310.         (int)(count & 0xffff), (int)((count>>16) & 0xffff) );
  311.         tw.puts(buf);
  312. #endif
  313.         iw = FindImageWindow(str);
  314.         iw->size( (int)(count & 0xffff), (int)((count>>16) & 0xffff) );
  315.         break;
  316.     default:
  317.         sprintf(buf,"Callback: Unknown message=%d\n",message);
  318.         tw.puts(buf);
  319.         break;
  320.     }
  321.     return 0;
  322. }
  323.  
  324.  
  325. #ifndef __WIN32__
  326. // This is a hack to cope with a GPF occuring in either Ghostscript
  327. // or a driver loaded by Ghostscript.  If a GPF occurs, gswin16.exe
  328. // is unloaded, but not gsdll16.dll.
  329. // Attempts to reload gswin16.exe will fail because gsdll16.dll
  330. // is already in use.  If this occurs, this code will unload
  331. // gsdll16.dll, EVEN IF SOMEONE ELSE IS USING IT.
  332.  
  333. // The DLL module name as it appears in the module definition file
  334. #define GSDLLNAME "GSDLL16"
  335. // These are the names of EXE modules that are known users
  336. // of the Ghostscript DLL.
  337. // If one of these is running, it is not safe to unload the DLL.
  338. #define GSEXE        "GSWIN16"
  339.  
  340. typedef HMODULE (WINAPI *TOOLMFN)(MODULEENTRY FAR *, LPCSTR);
  341.  
  342. static BOOL
  343. dllfix(void)
  344. {
  345. HMODULE hdll;            // module handle of DLL
  346. HMODULE hgswin16;        // module handle of Ghostscript
  347. MODULEENTRY me_dll;         // to contain details about DLL module
  348. MODULEENTRY me_gswin16;  // details about Ghostscript
  349. HINSTANCE htool;        // module handle of TOOLHELP.DLL
  350. TOOLMFN lpfnModuleFindName = NULL;
  351. char buf[256];
  352. BOOL err = FALSE;
  353.  
  354.     // load TOOLHELP.DLL
  355.     htool = LoadLibrary("TOOLHELP.DLL");
  356.     if ( htool <= HINSTANCE_ERROR )
  357.     err = TRUE;
  358.  
  359.     // get address of toolhelp function
  360.     if (!err) {
  361.     lpfnModuleFindName = (TOOLMFN)GetProcAddress(htool, "ModuleFindName");
  362.     err = !lpfnModuleFindName;
  363.     }
  364.  
  365.     // find handle for DLL
  366.     if (!err) {
  367.     memset(&me_dll, 0, sizeof(me_dll));
  368.     me_dll.dwSize = sizeof(me_dll);
  369.     hdll = lpfnModuleFindName(&me_dll, GSDLLNAME);
  370.     }
  371.  
  372.     // look for Ghostscript EXE module
  373.     // This should be found because we are it
  374.     if (!err) {
  375.     memset(&me_gswin16, 0, sizeof(me_gswin16));
  376.     me_gswin16.dwSize = sizeof(me_gswin16);
  377.     hgswin16 = lpfnModuleFindName(&me_gswin16, GSEXE);
  378.     }
  379.  
  380. #ifdef DEBUG
  381.     // for debugging, show what we have found
  382.     if (hdll) {
  383.     wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s",
  384.     me_dll.szModule, me_dll.hModule, me_dll.wcUsage, me_dll.szExePath);
  385.     MessageBox((HWND)NULL, buf, szAppName, MB_OK);
  386.     }
  387.     if (hgswin16) {
  388.     wsprintf(buf, "Found %s\nModule Handle=%d\nModule Usage=%d\nModule Path=%s",
  389.     me_gswin16.szModule, me_gswin16.hModule, me_gswin16.wcUsage,
  390.     me_gswin16.szExePath);
  391.     MessageBox((HWND)NULL, buf, szAppName, MB_OK);
  392.     }
  393. #endif
  394.  
  395.     // if DLL loaded and Ghostscript is not running...
  396.     if (!err &&
  397.     hdll &&         // Ghostscript DLL loaded
  398.     (hgswin16 && me_gswin16.wcUsage == 1) // Only one copy of Ghostscript EXE
  399.     ) {
  400.     wsprintf(buf, "%s is loaded but does not appear to be in use by Ghostscript. Unload it?", GSDLLNAME);
  401.     if (MessageBox((HWND)NULL, buf, szAppName, MB_YESNO | MB_ICONHAND) == IDYES)
  402.         // If DLL is really in use, we about to cause a disaster
  403.         while (GetModuleUsage(hdll))
  404.         FreeLibrary(hdll);
  405.     }
  406.  
  407.     if (htool)
  408.     FreeLibrary(htool);
  409.     return err;
  410. }
  411. #endif
  412.  
  413.